"use client"; import { useState, useEffect } from "react"; import { useParams } from "next/navigation"; import { useAuth } from "@/context/AuthContext"; import Button from "@/components/shared/Button"; import { Calendar } from "@/components/ui/calendar"; import { Form, FormControl, FormField, FormItem } from "@/components/ui/form"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; import { cn } from "@/lib/utils"; import { format } from "date-fns"; import { CalendarIcon } from "lucide-react"; import { useForm } from "react-hook-form"; export default function ApplicationLogsPage() { const { application_id } = useParams(); const [logs, setLogs] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(""); const [isGeneratingDummy, setIsGeneratingDummy] = useState(false); const [pageSize] = useState(20); // Default page size const [cursor, setCursor] = useState(null); const [hasMore, setHasMore] = useState(false); const [isLoadingMore, setIsLoadingMore] = useState(false); const [logLevel, setLogLevel] = useState(""); const [startTime, setStartTime] = useState(""); const [endTime, setEndTime] = useState(""); const [applicationName, setApplicationName] = useState(""); useEffect(() => { fetchLogs(); }, [application_id, logLevel, startTime, endTime]); async function fetchLogs(nextCursor = null) { if (!application_id) return; setIsLoading(true); try { const response = await fetch( "http://localhost:8080/twirp/logs.LogsService/GetLogs", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: localStorage.getItem("token"), application_id: application_id, page_size: pageSize, cursor: nextCursor, log_level: logLevel === "ALL" ? "" : logLevel, start_time: startTime, end_time: endTime, }), }, ); const data = await response.json(); if (data.logs) { if (nextCursor) { setLogs((prev) => [...prev, ...data.logs]); } else { setLogs(data.logs); } setHasMore(data.has_more); setCursor(data.next_cursor); setApplicationName(data.application_name); } } catch (error) { console.error("Error fetching logs:", error); setError("Failed to load logs"); } finally { setIsLoading(false); setIsLoadingMore(false); } } async function generateDummyLogs() { if (!application_id) return; setIsGeneratingDummy(true); try { const response = await fetch( "http://localhost:8080/twirp/logs.LogsService/GenerateDummyLogs", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ token: localStorage.getItem("token"), application_id: application_id, }), }, ); if (response.ok) { await fetchLogs(); // Refresh logs after generating } } catch (error) { console.error("Error generating dummy logs:", error); setError("Failed to generate dummy logs"); } finally { setIsGeneratingDummy(false); } } async function loadMore() { if (!hasMore || isLoadingMore) return; setIsLoadingMore(true); await fetchLogs(cursor); } const logLevelColors = { DEBUG: "text-gray-600", INFO: "text-blue-600", WARN: "text-yellow-600", ERROR: "text-red-600", FATAL: "text-red-800", }; const handleFilterSubmit = (data) => { setLogLevel(data.logLevels[0] || ""); setStartTime(data.startTime ? data.startTime.toISOString() : ""); setEndTime(data.endTime ? data.endTime.toISOString() : ""); }; return (

{applicationName} Logs

{error && (
{error}
)} {logs.length === 0 ? (

No logs found this means wither this application has no logs or the filters applied are too restrictive.

) : ( <>
{logs.map((log) => ( ))}
Level Message Timestamp
{log.level} {log.message} {new Date(log.timestamp).toLocaleString()}
{logs.length > 0 && (
{hasMore ? ( ) : (

No more logs

)}
)} )}
); } function FiltersForm({ logLevel, setLogLevel, startTime, setStartTime, endTime, setEndTime, onSubmit, }) { const form = useForm({ defaultValues: { logLevels: logLevel ? [logLevel] : [], startTime: startTime ? new Date(startTime) : undefined, endTime: endTime ? new Date(endTime) : undefined, }, }); const handleClearFilters = () => { form.reset({ logLevels: [], startTime: undefined, endTime: undefined, }); setLogLevel(""); setStartTime(""); setEndTime(""); onSubmit(form.getValues()); }; const isFormChanged = () => { const values = form.getValues(); return ( values.logLevels.length > 0 || values.startTime !== undefined || values.endTime !== undefined ); }; const handleSubmit = (data) => { setLogLevel(data.logLevels[0] === "ALL" ? "" : data.logLevels[0] || ""); setStartTime(data.startTime ? data.startTime.toISOString() : ""); setEndTime(data.endTime ? data.endTime.toISOString() : ""); onSubmit(data); }; return (
( )} /> (
{ if (field.value && e.target.value) { const [hours, minutes] = e.target.value.split(":"); const newDate = new Date(field.value); newDate.setHours(parseInt(hours)); newDate.setMinutes(parseInt(minutes)); field.onChange(newDate); } }} value={ field.value ? `${field.value.getHours().toString().padStart(2, "0")}:${field.value .getMinutes() .toString() .padStart(2, "0")}` : "" } />
)} /> (
{ if (field.value && e.target.value) { const [hours, minutes] = e.target.value.split(":"); const newDate = new Date(field.value); newDate.setHours(parseInt(hours)); newDate.setMinutes(parseInt(minutes)); field.onChange(newDate); } }} value={ field.value ? `${field.value.getHours().toString().padStart(2, "0")}:${field.value .getMinutes() .toString() .padStart(2, "0")}` : "" } />
)} />
); }